use std::ffi::{CStr, CString};
use std::os::raw::{c_char, c_uint};
use std::ptr;

use crate::Program;
use crate::classes::*;
use crate::enums::*;

// C-compatible enums
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub enum COptionValue {
    NotSet = 0,
    On = 1,
    Off = 2,
    Error = 4,
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub enum CPolicyName {
    DEP = 0,
    ASLR = 1,
    StrictHandle = 2,
    SystemCalls = 3,
    ExtensionPoints = 4,
    DynamicCode = 5,
    ControlFlowGuard = 6,
    SignedBinaries = 7,
    Fonts = 8,
    ImageLoad = 9,
    Payload = 10,
    ChildProcess = 11,
    UserShadowStack = 12,
    SEHOP = 13,
    Heap = 14,
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub enum CMitigationOptions {
    DEP = 0,
    EmulateAtlThunks = 1,
    ForceRelocateImages = 2,
    RequireInfo = 3,
    BottomUp = 4,
    HighEntropy = 5,
    StrictHandle = 6,
    DisableWin32kSystemCalls = 7,
    AuditSystemCall = 8,
    DisableExtensionPoints = 9,
    DisableFsctlSystemCalls = 10,
    AuditFsctlSystemCall = 11,
    BlockDynamicCode = 12,
    AllowThreadsToOptOut = 13,
    AuditDynamicCode = 14,
    CFG = 15,
    SuppressExports = 16,
    StrictCFG = 17,
    MicrosoftSignedOnly = 18,
    AllowStoreSignedBinaries = 19,
    AuditMicrosoftSigned = 20,
    AuditStoreSigned = 21,
    EnforceModuleDependencySigning = 22,
    DisableNonSystemFonts = 23,
    AuditFont = 24,
    BlockRemoteImageLoads = 25,
    BlockLowLabelImageLoads = 26,
    PreferSystem32 = 27,
    AuditRemoteImageLoads = 28,
    AuditLowLabelImageLoads = 29,
    AuditPreferSystem32 = 30,
    EnableExportAddressFilter = 31,
    AuditEnableExportAddressFilter = 32,
    EnableExportAddressFilterPlus = 33,
    AuditEnableExportAddressFilterPlus = 34,
    EnableImportAddressFilter = 35,
    AuditEnableImportAddressFilter = 36,
    EnableRopStackPivot = 37,
    AuditEnableRopStackPivot = 38,
    EnableRopCallerCheck = 39,
    AuditEnableRopCallerCheck = 40,
    EnableRopSimExec = 41,
    AuditEnableRopSimExec = 42,
    SEHOP = 43,
    AuditSEHOP = 44,
    SEHOPTelemetry = 45,
    TerminateOnError = 46,
    DisallowChildProcessCreation = 47,
    AuditChildProcess = 48,
    UserShadowStack = 49,
    UserShadowStackStrictMode = 50,
    AuditUserShadowStack = 51,
}

// C-compatible structs
#[repr(C)]
#[derive(Debug, Clone)]
pub struct CStringArray {
    pub data: *mut *mut c_char,
    pub length: usize,
}

#[repr(C)]
#[derive(Debug, Clone)]
pub struct CMitigationOptionsArray {
    pub data: *mut CMitigationOptions,
    pub length: usize,
}

#[repr(C)]
#[derive(Debug, Clone)]
pub struct CPolicyOption {
    pub policy_name: CPolicyName,
    pub option_name: c_uint,
    pub option_value: COptionValue,
}

#[repr(C)]
#[derive(Debug, Clone)]
pub struct CPolicyOptionArray {
    pub data: *mut CPolicyOption,
    pub length: usize,
}

#[repr(C)]
#[derive(Debug, Clone)]
pub struct CForceOption {
    pub policy_name: CPolicyName,
    pub force_name: c_uint,
    pub is_forced: u8,
}

#[repr(C)]
#[derive(Debug, Clone)]
pub struct CForceOptionArray {
    pub data: *mut CForceOption,
    pub length: usize,
}

#[repr(C)]
#[derive(Debug, Clone)]
pub struct CProcessMitigations {
    pub process_name: *mut c_char,
    pub source: *mut c_char,
    pub id: c_uint,
    pub policy_options: CPolicyOptionArray,
}

#[repr(C)]
#[derive(Debug, Clone)]
pub struct CProcessMitigationsArray {
    pub data: *mut CProcessMitigations,
    pub length: usize,
}

#[repr(C)]
#[derive(Debug, Clone)]
pub struct CAppMitigations {
    pub process_name: *mut c_char,
    pub source: *mut c_char,
    pub policy_options: CPolicyOptionArray,
    pub force_options: CForceOptionArray,
    pub eaf_modules: CStringArray,
}

#[repr(C)]
#[derive(Debug, Clone)]
pub struct CAppMitigationsArray {
    pub data: *mut CAppMitigations,
    pub length: usize,
}

#[repr(C)]
#[derive(Debug, Clone)]
pub struct CAppResult {
    pub is_success: u8,
    pub error_message: *mut c_char,
}

// Conversion functions
impl From<OptionValue> for COptionValue {
    fn from(value: OptionValue) -> Self {
        match value {
            OptionValue::NotSet => COptionValue::NotSet,
            OptionValue::On => COptionValue::On,
            OptionValue::Off => COptionValue::Off,
            OptionValue::Error => COptionValue::Error,
        }
    }
}

impl From<COptionValue> for OptionValue {
    fn from(value: COptionValue) -> Self {
        match value {
            COptionValue::NotSet => OptionValue::NotSet,
            COptionValue::On => OptionValue::On,
            COptionValue::Off => OptionValue::Off,
            COptionValue::Error => OptionValue::Error,
        }
    }
}

impl From<PolicyName> for CPolicyName {
    fn from(value: PolicyName) -> Self {
        match value {
            PolicyName::DEP => CPolicyName::DEP,
            PolicyName::ASLR => CPolicyName::ASLR,
            PolicyName::StrictHandle => CPolicyName::StrictHandle,
            PolicyName::SystemCalls => CPolicyName::SystemCalls,
            PolicyName::ExtensionPoints => CPolicyName::ExtensionPoints,
            PolicyName::DynamicCode => CPolicyName::DynamicCode,
            PolicyName::ControlFlowGuard => CPolicyName::ControlFlowGuard,
            PolicyName::SignedBinaries => CPolicyName::SignedBinaries,
            PolicyName::Fonts => CPolicyName::Fonts,
            PolicyName::ImageLoad => CPolicyName::ImageLoad,
            PolicyName::Payload => CPolicyName::Payload,
            PolicyName::ChildProcess => CPolicyName::ChildProcess,
            PolicyName::UserShadowStack => CPolicyName::UserShadowStack,
            PolicyName::SEHOP => CPolicyName::SEHOP,
            PolicyName::Heap => CPolicyName::Heap,
        }
    }
}

impl From<CPolicyName> for PolicyName {
    fn from(value: CPolicyName) -> Self {
        match value {
            CPolicyName::DEP => PolicyName::DEP,
            CPolicyName::ASLR => PolicyName::ASLR,
            CPolicyName::StrictHandle => PolicyName::StrictHandle,
            CPolicyName::SystemCalls => PolicyName::SystemCalls,
            CPolicyName::ExtensionPoints => PolicyName::ExtensionPoints,
            CPolicyName::DynamicCode => PolicyName::DynamicCode,
            CPolicyName::ControlFlowGuard => PolicyName::ControlFlowGuard,
            CPolicyName::SignedBinaries => PolicyName::SignedBinaries,
            CPolicyName::Fonts => PolicyName::Fonts,
            CPolicyName::ImageLoad => PolicyName::ImageLoad,
            CPolicyName::Payload => PolicyName::Payload,
            CPolicyName::ChildProcess => PolicyName::ChildProcess,
            CPolicyName::UserShadowStack => PolicyName::UserShadowStack,
            CPolicyName::SEHOP => PolicyName::SEHOP,
            CPolicyName::Heap => PolicyName::Heap,
        }
    }
}

impl From<MitigationOptions> for CMitigationOptions {
    fn from(value: MitigationOptions) -> Self {
        match value {
            MitigationOptions::DEP => CMitigationOptions::DEP,
            MitigationOptions::EmulateAtlThunks => CMitigationOptions::EmulateAtlThunks,
            MitigationOptions::ForceRelocateImages => CMitigationOptions::ForceRelocateImages,
            MitigationOptions::RequireInfo => CMitigationOptions::RequireInfo,
            MitigationOptions::BottomUp => CMitigationOptions::BottomUp,
            MitigationOptions::HighEntropy => CMitigationOptions::HighEntropy,
            MitigationOptions::StrictHandle => CMitigationOptions::StrictHandle,
            MitigationOptions::DisableWin32kSystemCalls => {
                CMitigationOptions::DisableWin32kSystemCalls
            }
            MitigationOptions::AuditSystemCall => CMitigationOptions::AuditSystemCall,
            MitigationOptions::DisableExtensionPoints => CMitigationOptions::DisableExtensionPoints,
            MitigationOptions::DisableFsctlSystemCalls => {
                CMitigationOptions::DisableFsctlSystemCalls
            }
            MitigationOptions::AuditFsctlSystemCall => CMitigationOptions::AuditFsctlSystemCall,
            MitigationOptions::BlockDynamicCode => CMitigationOptions::BlockDynamicCode,
            MitigationOptions::AllowThreadsToOptOut => CMitigationOptions::AllowThreadsToOptOut,
            MitigationOptions::AuditDynamicCode => CMitigationOptions::AuditDynamicCode,
            MitigationOptions::CFG => CMitigationOptions::CFG,
            MitigationOptions::SuppressExports => CMitigationOptions::SuppressExports,
            MitigationOptions::StrictCFG => CMitigationOptions::StrictCFG,
            MitigationOptions::MicrosoftSignedOnly => CMitigationOptions::MicrosoftSignedOnly,
            MitigationOptions::AllowStoreSignedBinaries => {
                CMitigationOptions::AllowStoreSignedBinaries
            }
            MitigationOptions::AuditMicrosoftSigned => CMitigationOptions::AuditMicrosoftSigned,
            MitigationOptions::AuditStoreSigned => CMitigationOptions::AuditStoreSigned,
            MitigationOptions::EnforceModuleDependencySigning => {
                CMitigationOptions::EnforceModuleDependencySigning
            }
            MitigationOptions::DisableNonSystemFonts => CMitigationOptions::DisableNonSystemFonts,
            MitigationOptions::AuditFont => CMitigationOptions::AuditFont,
            MitigationOptions::BlockRemoteImageLoads => CMitigationOptions::BlockRemoteImageLoads,
            MitigationOptions::BlockLowLabelImageLoads => {
                CMitigationOptions::BlockLowLabelImageLoads
            }
            MitigationOptions::PreferSystem32 => CMitigationOptions::PreferSystem32,
            MitigationOptions::AuditRemoteImageLoads => CMitigationOptions::AuditRemoteImageLoads,
            MitigationOptions::AuditLowLabelImageLoads => {
                CMitigationOptions::AuditLowLabelImageLoads
            }
            MitigationOptions::AuditPreferSystem32 => CMitigationOptions::AuditPreferSystem32,
            MitigationOptions::EnableExportAddressFilter => {
                CMitigationOptions::EnableExportAddressFilter
            }
            MitigationOptions::AuditEnableExportAddressFilter => {
                CMitigationOptions::AuditEnableExportAddressFilter
            }
            MitigationOptions::EnableExportAddressFilterPlus => {
                CMitigationOptions::EnableExportAddressFilterPlus
            }
            MitigationOptions::AuditEnableExportAddressFilterPlus => {
                CMitigationOptions::AuditEnableExportAddressFilterPlus
            }
            MitigationOptions::EnableImportAddressFilter => {
                CMitigationOptions::EnableImportAddressFilter
            }
            MitigationOptions::AuditEnableImportAddressFilter => {
                CMitigationOptions::AuditEnableImportAddressFilter
            }
            MitigationOptions::EnableRopStackPivot => CMitigationOptions::EnableRopStackPivot,
            MitigationOptions::AuditEnableRopStackPivot => {
                CMitigationOptions::AuditEnableRopStackPivot
            }
            MitigationOptions::EnableRopCallerCheck => CMitigationOptions::EnableRopCallerCheck,
            MitigationOptions::AuditEnableRopCallerCheck => {
                CMitigationOptions::AuditEnableRopCallerCheck
            }
            MitigationOptions::EnableRopSimExec => CMitigationOptions::EnableRopSimExec,
            MitigationOptions::AuditEnableRopSimExec => CMitigationOptions::AuditEnableRopSimExec,
            MitigationOptions::SEHOP => CMitigationOptions::SEHOP,
            MitigationOptions::AuditSEHOP => CMitigationOptions::AuditSEHOP,
            MitigationOptions::SEHOPTelemetry => CMitigationOptions::SEHOPTelemetry,
            MitigationOptions::TerminateOnError => CMitigationOptions::TerminateOnError,
            MitigationOptions::DisallowChildProcessCreation => {
                CMitigationOptions::DisallowChildProcessCreation
            }
            MitigationOptions::AuditChildProcess => CMitigationOptions::AuditChildProcess,
            MitigationOptions::UserShadowStack => CMitigationOptions::UserShadowStack,
            MitigationOptions::UserShadowStackStrictMode => {
                CMitigationOptions::UserShadowStackStrictMode
            }
            MitigationOptions::AuditUserShadowStack => CMitigationOptions::AuditUserShadowStack,
        }
    }
}

impl From<CMitigationOptions> for MitigationOptions {
    fn from(value: CMitigationOptions) -> Self {
        match value {
            CMitigationOptions::DEP => MitigationOptions::DEP,
            CMitigationOptions::EmulateAtlThunks => MitigationOptions::EmulateAtlThunks,
            CMitigationOptions::ForceRelocateImages => MitigationOptions::ForceRelocateImages,
            CMitigationOptions::RequireInfo => MitigationOptions::RequireInfo,
            CMitigationOptions::BottomUp => MitigationOptions::BottomUp,
            CMitigationOptions::HighEntropy => MitigationOptions::HighEntropy,
            CMitigationOptions::StrictHandle => MitigationOptions::StrictHandle,
            CMitigationOptions::DisableWin32kSystemCalls => {
                MitigationOptions::DisableWin32kSystemCalls
            }
            CMitigationOptions::AuditSystemCall => MitigationOptions::AuditSystemCall,
            CMitigationOptions::DisableExtensionPoints => MitigationOptions::DisableExtensionPoints,
            CMitigationOptions::DisableFsctlSystemCalls => {
                MitigationOptions::DisableFsctlSystemCalls
            }
            CMitigationOptions::AuditFsctlSystemCall => MitigationOptions::AuditFsctlSystemCall,
            CMitigationOptions::BlockDynamicCode => MitigationOptions::BlockDynamicCode,
            CMitigationOptions::AllowThreadsToOptOut => MitigationOptions::AllowThreadsToOptOut,
            CMitigationOptions::AuditDynamicCode => MitigationOptions::AuditDynamicCode,
            CMitigationOptions::CFG => MitigationOptions::CFG,
            CMitigationOptions::SuppressExports => MitigationOptions::SuppressExports,
            CMitigationOptions::StrictCFG => MitigationOptions::StrictCFG,
            CMitigationOptions::MicrosoftSignedOnly => MitigationOptions::MicrosoftSignedOnly,
            CMitigationOptions::AllowStoreSignedBinaries => {
                MitigationOptions::AllowStoreSignedBinaries
            }
            CMitigationOptions::AuditMicrosoftSigned => MitigationOptions::AuditMicrosoftSigned,
            CMitigationOptions::AuditStoreSigned => MitigationOptions::AuditStoreSigned,
            CMitigationOptions::EnforceModuleDependencySigning => {
                MitigationOptions::EnforceModuleDependencySigning
            }
            CMitigationOptions::DisableNonSystemFonts => MitigationOptions::DisableNonSystemFonts,
            CMitigationOptions::AuditFont => MitigationOptions::AuditFont,
            CMitigationOptions::BlockRemoteImageLoads => MitigationOptions::BlockRemoteImageLoads,
            CMitigationOptions::BlockLowLabelImageLoads => {
                MitigationOptions::BlockLowLabelImageLoads
            }
            CMitigationOptions::PreferSystem32 => MitigationOptions::PreferSystem32,
            CMitigationOptions::AuditRemoteImageLoads => MitigationOptions::AuditRemoteImageLoads,
            CMitigationOptions::AuditLowLabelImageLoads => {
                MitigationOptions::AuditLowLabelImageLoads
            }
            CMitigationOptions::AuditPreferSystem32 => MitigationOptions::AuditPreferSystem32,
            CMitigationOptions::EnableExportAddressFilter => {
                MitigationOptions::EnableExportAddressFilter
            }
            CMitigationOptions::AuditEnableExportAddressFilter => {
                MitigationOptions::AuditEnableExportAddressFilter
            }
            CMitigationOptions::EnableExportAddressFilterPlus => {
                MitigationOptions::EnableExportAddressFilterPlus
            }
            CMitigationOptions::AuditEnableExportAddressFilterPlus => {
                MitigationOptions::AuditEnableExportAddressFilterPlus
            }
            CMitigationOptions::EnableImportAddressFilter => {
                MitigationOptions::EnableImportAddressFilter
            }
            CMitigationOptions::AuditEnableImportAddressFilter => {
                MitigationOptions::AuditEnableImportAddressFilter
            }
            CMitigationOptions::EnableRopStackPivot => MitigationOptions::EnableRopStackPivot,
            CMitigationOptions::AuditEnableRopStackPivot => {
                MitigationOptions::AuditEnableRopStackPivot
            }
            CMitigationOptions::EnableRopCallerCheck => MitigationOptions::EnableRopCallerCheck,
            CMitigationOptions::AuditEnableRopCallerCheck => {
                MitigationOptions::AuditEnableRopCallerCheck
            }
            CMitigationOptions::EnableRopSimExec => MitigationOptions::EnableRopSimExec,
            CMitigationOptions::AuditEnableRopSimExec => MitigationOptions::AuditEnableRopSimExec,
            CMitigationOptions::SEHOP => MitigationOptions::SEHOP,
            CMitigationOptions::AuditSEHOP => MitigationOptions::AuditSEHOP,
            CMitigationOptions::SEHOPTelemetry => MitigationOptions::SEHOPTelemetry,
            CMitigationOptions::TerminateOnError => MitigationOptions::TerminateOnError,
            CMitigationOptions::DisallowChildProcessCreation => {
                MitigationOptions::DisallowChildProcessCreation
            }
            CMitigationOptions::AuditChildProcess => MitigationOptions::AuditChildProcess,
            CMitigationOptions::UserShadowStack => MitigationOptions::UserShadowStack,
            CMitigationOptions::UserShadowStackStrictMode => {
                MitigationOptions::UserShadowStackStrictMode
            }
            CMitigationOptions::AuditUserShadowStack => MitigationOptions::AuditUserShadowStack,
        }
    }
}

// Helper functions for string conversion
unsafe fn c_string_to_rust(c_str: *const c_char) -> String {
    if c_str.is_null() {
        return String::new();
    }
    unsafe { CStr::from_ptr(c_str) }
        .to_string_lossy()
        .to_string()
}

fn rust_string_to_c(s: &str) -> *mut c_char {
    match CString::new(s) {
        Ok(c_string) => c_string.into_raw(),
        Err(_) => ptr::null_mut(),
    }
}

// Helper functions for converting collections
fn rust_vec_to_c_array<T>(vec: Vec<T>) -> (*mut T, usize) {
    if vec.is_empty() {
        return (ptr::null_mut(), 0);
    }
    let len = vec.len();
    let ptr = Box::into_raw(vec.into_boxed_slice()) as *mut T;
    (ptr, len)
}

fn strings_to_c_array(strings: Vec<String>) -> CStringArray {
    if strings.is_empty() {
        return CStringArray {
            data: ptr::null_mut(),
            length: 0,
        };
    }

    let c_strings: Vec<*mut c_char> = strings.iter().map(|s| rust_string_to_c(s)).collect();

    let (data, length) = rust_vec_to_c_array(c_strings);
    CStringArray { data, length }
}

// Policy option name to u32 conversion
fn policy_option_name_to_u32(option: PolicyOptionName) -> u32 {
    option as u32
}

// Force name to u32 conversion
fn force_name_to_u32(force: ForceName) -> u32 {
    force as u32
}

// Convert ProcessMitigations to C structure
fn process_mitigations_to_c(mitigations: &ProcessMitigations) -> CProcessMitigations {
    let mut policy_options = Vec::new();

    for (policy_name, policy_container) in &mitigations.policies {
        let c_policy_name = CPolicyName::from(*policy_name);
        let all_options = policy_container.get_all_options();

        for option in all_options {
            let option_value = policy_container.get_policy(option);
            policy_options.push(CPolicyOption {
                policy_name: c_policy_name,
                option_name: policy_option_name_to_u32(option),
                option_value: COptionValue::from(option_value),
            });
        }
    }

    let (data, length) = rust_vec_to_c_array(policy_options);

    CProcessMitigations {
        process_name: rust_string_to_c(&mitigations.process_name),
        source: rust_string_to_c(&mitigations.source),
        id: mitigations.id,
        policy_options: CPolicyOptionArray { data, length },
    }
}

// Convert AppMitigations to C structure
fn app_mitigations_to_c(mitigations: &AppMitigations) -> CAppMitigations {
    let mut policy_options = Vec::new();
    let mut force_options = Vec::new();
    let mut eaf_modules = Vec::new();

    for (policy_name, policy_container) in &mitigations.policies {
        let c_policy_name = CPolicyName::from(*policy_name);
        let all_options = policy_container.get_all_options();

        for option in all_options {
            let option_value = policy_container.get_policy(option);
            policy_options.push(CPolicyOption {
                policy_name: c_policy_name,
                option_name: policy_option_name_to_u32(option),
                option_value: COptionValue::from(option_value),
            });
        }

        // Handle force options based on policy type
        match policy_container {
            AppPolicyContainer::Dep(p) => {
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::DEP),
                    is_forced: if p.override_dep() { 1 } else { 0 },
                });
            }
            AppPolicyContainer::Aslr(p) => {
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::ForceRelocateImages),
                    is_forced: if p.override_force_relocate_images() {
                        1
                    } else {
                        0
                    },
                });
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::BottomUp),
                    is_forced: if p.override_bottom_up() { 1 } else { 0 },
                });
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::HighEntropy),
                    is_forced: if p.override_high_entropy() { 1 } else { 0 },
                });
            }
            AppPolicyContainer::StrictHandle(p) => {
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::StrictHandle),
                    is_forced: if p.override_strict_handle() { 1 } else { 0 },
                });
            }
            AppPolicyContainer::SystemCalls(p) => {
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::SystemCall),
                    is_forced: if p.override_system_call() { 1 } else { 0 },
                });
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::DisableFsctlSystem),
                    is_forced: if p.override_fsctl_system_call() { 1 } else { 0 },
                });
            }
            AppPolicyContainer::ExtensionPoints(p) => {
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::ExtensionPoint),
                    is_forced: if p.override_extension_point() { 1 } else { 0 },
                });
            }
            AppPolicyContainer::DynamicCode(p) => {
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::DynamicCode),
                    is_forced: if p.override_dynamic_code() { 1 } else { 0 },
                });
            }
            AppPolicyContainer::ControlFlowGuard(p) => {
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::CFG),
                    is_forced: if p.override_cfg() { 1 } else { 0 },
                });
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::StrictCFG),
                    is_forced: if p.override_strict_cfg() { 1 } else { 0 },
                });
            }
            AppPolicyContainer::SignedBinaries(p) => {
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::MicrosoftSignedOnly),
                    is_forced: if p.override_microsoft_signed_only() {
                        1
                    } else {
                        0
                    },
                });
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::EnforceModuleDependencySigning),
                    is_forced: if p.override_enforce_module_dependency_signing() {
                        1
                    } else {
                        0
                    },
                });
            }
            AppPolicyContainer::Fonts(p) => {
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::FontDisable),
                    is_forced: if p.override_font_disable() { 1 } else { 0 },
                });
            }
            AppPolicyContainer::ImageLoad(p) => {
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::BlockRemoteImageLoads),
                    is_forced: if p.override_block_remote_image_loads() {
                        1
                    } else {
                        0
                    },
                });
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::BlockLowLabel),
                    is_forced: if p.override_block_low_label() { 1 } else { 0 },
                });
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::PreferSystem32),
                    is_forced: if p.override_prefer_system32() { 1 } else { 0 },
                });
            }
            AppPolicyContainer::Payload(p) => {
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::EnableExportAddressFilter),
                    is_forced: if p.override_enable_export_address_filter() {
                        1
                    } else {
                        0
                    },
                });
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::EnableExportAddressFilterPlus),
                    is_forced: if p.override_enable_export_address_filter_plus() {
                        1
                    } else {
                        0
                    },
                });
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::EnableImportAddressFilter),
                    is_forced: if p.override_enable_import_address_filter() {
                        1
                    } else {
                        0
                    },
                });
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::EnableRopStackPivot),
                    is_forced: if p.override_enable_rop_stack_pivot() {
                        1
                    } else {
                        0
                    },
                });
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::EnableRopCallerCheck),
                    is_forced: if p.override_enable_rop_caller_check() {
                        1
                    } else {
                        0
                    },
                });
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::EnableRopSimExec),
                    is_forced: if p.override_enable_rop_sim_exec() {
                        1
                    } else {
                        0
                    },
                });
                eaf_modules.extend(p.eaf_modules.clone());
            }
            AppPolicyContainer::ChildProcess(p) => {
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::ChildProcess),
                    is_forced: if p.override_child_process() { 1 } else { 0 },
                });
            }
            AppPolicyContainer::UserShadowStack(p) => {
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::UserShadowStack),
                    is_forced: if p.override_user_shadow_stack() { 1 } else { 0 },
                });
            }
            AppPolicyContainer::SEHOP(p) => {
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::SEHOP),
                    is_forced: if p.override_sehop() { 1 } else { 0 },
                });
            }
            AppPolicyContainer::Heap(p) => {
                force_options.push(CForceOption {
                    policy_name: c_policy_name,
                    force_name: force_name_to_u32(ForceName::Heap),
                    is_forced: if p.override_heap() { 1 } else { 0 },
                });
            }
        }
    }

    let (policy_data, policy_length) = rust_vec_to_c_array(policy_options);
    let (force_data, force_length) = rust_vec_to_c_array(force_options);

    CAppMitigations {
        process_name: rust_string_to_c(&mitigations.process_name),
        source: rust_string_to_c(&mitigations.source),
        policy_options: CPolicyOptionArray {
            data: policy_data,
            length: policy_length,
        },
        force_options: CForceOptionArray {
            data: force_data,
            length: force_length,
        },
        eaf_modules: strings_to_c_array(eaf_modules),
    }
}

// Exported C functions
#[unsafe(no_mangle)]
pub extern "C" fn get_from_running_process_name(
    process_name: *const c_char,
    result: *mut CProcessMitigationsArray,
) -> CAppResult {
    if process_name.is_null() || result.is_null() {
        return CAppResult {
            is_success: 0,
            error_message: rust_string_to_c("Invalid parameters"),
        };
    }

    unsafe {
        let process_name_str = c_string_to_rust(process_name);

        match Program::get_from_running_process_name(&process_name_str) {
            app_result if app_result.is_success => {
                if let Some(mitigations_vec) = app_result.value {
                    let c_mitigations: Vec<CProcessMitigations> = mitigations_vec
                        .iter()
                        .map(|m| process_mitigations_to_c(m))
                        .collect();

                    let (data, length) = rust_vec_to_c_array(c_mitigations);

                    *result = CProcessMitigationsArray { data, length };

                    CAppResult {
                        is_success: 1,
                        error_message: ptr::null_mut(),
                    }
                } else {
                    CAppResult {
                        is_success: 0,
                        error_message: rust_string_to_c("No value returned"),
                    }
                }
            }
            app_result => CAppResult {
                is_success: 0,
                error_message: rust_string_to_c(&app_result.error),
            },
        }
    }
}

#[unsafe(no_mangle)]
pub extern "C" fn get_system_policy(result: *mut CAppMitigations) -> CAppResult {
    if result.is_null() {
        return CAppResult {
            is_success: 0,
            error_message: rust_string_to_c("Invalid parameters"),
        };
    }

    unsafe {
        match Program::get_system_policy() {
            app_result if app_result.is_success => {
                if let Some(mitigations) = app_result.value {
                    *result = app_mitigations_to_c(&mitigations);

                    CAppResult {
                        is_success: 1,
                        error_message: ptr::null_mut(),
                    }
                } else {
                    CAppResult {
                        is_success: 0,
                        error_message: rust_string_to_c("No value returned"),
                    }
                }
            }
            app_result => CAppResult {
                is_success: 0,
                error_message: rust_string_to_c(&app_result.error),
            },
        }
    }
}

#[unsafe(no_mangle)]
pub extern "C" fn get_full_policies_for_all_processes(
    result: *mut CAppMitigationsArray,
) -> CAppResult {
    if result.is_null() {
        return CAppResult {
            is_success: 0,
            error_message: rust_string_to_c("Invalid parameters"),
        };
    }

    unsafe {
        match Program::get_full_policies_for_all_processes() {
            app_result if app_result.is_success => {
                if let Some(mitigations_vec) = app_result.value {
                    let c_mitigations: Vec<CAppMitigations> = mitigations_vec
                        .iter()
                        .map(|m| app_mitigations_to_c(m))
                        .collect();

                    let (data, length) = rust_vec_to_c_array(c_mitigations);

                    *result = CAppMitigationsArray { data, length };

                    CAppResult {
                        is_success: 1,
                        error_message: ptr::null_mut(),
                    }
                } else {
                    CAppResult {
                        is_success: 0,
                        error_message: rust_string_to_c("No value returned"),
                    }
                }
            }
            app_result => CAppResult {
                is_success: 0,
                error_message: rust_string_to_c(&app_result.error),
            },
        }
    }
}

#[unsafe(no_mangle)]
pub extern "C" fn get_policy_from_registry_by_name(
    process_name: *const c_char,
    result: *mut CAppMitigationsArray,
) -> CAppResult {
    if process_name.is_null() || result.is_null() {
        return CAppResult {
            is_success: 0,
            error_message: rust_string_to_c("Invalid parameters"),
        };
    }

    unsafe {
        let process_name_str = c_string_to_rust(process_name);

        match Program::get_policy_from_registry_by_name(&process_name_str) {
            app_result if app_result.is_success => {
                if let Some(mitigations_vec) = app_result.value {
                    let c_mitigations: Vec<CAppMitigations> = mitigations_vec
                        .iter()
                        .map(|m| app_mitigations_to_c(m))
                        .collect();

                    let (data, length) = rust_vec_to_c_array(c_mitigations);

                    *result = CAppMitigationsArray { data, length };

                    CAppResult {
                        is_success: 1,
                        error_message: ptr::null_mut(),
                    }
                } else {
                    CAppResult {
                        is_success: 0,
                        error_message: rust_string_to_c("No value returned"),
                    }
                }
            }
            app_result => CAppResult {
                is_success: 0,
                error_message: rust_string_to_c(&app_result.error),
            },
        }
    }
}

#[unsafe(no_mangle)]
pub extern "C" fn add_mitigations_for_process(
    process_name: *const c_char,
    disable_list: *const CMitigationOptions,
    disable_count: usize,
    enable_list: *const CMitigationOptions,
    enable_count: usize,
    eaf_modules: *const *const c_char,
    eaf_modules_count: usize,
    is_force: *const c_char,
    is_remove: u8,
    is_reset: u8,
) -> CAppResult {
    if process_name.is_null() {
        return CAppResult {
            is_success: 0,
            error_message: rust_string_to_c("Invalid parameters"),
        };
    }

    unsafe {
        let process_name_str = c_string_to_rust(process_name);

        let disable_options = if disable_list.is_null() || disable_count == 0 {
            None
        } else {
            let slice = std::slice::from_raw_parts(disable_list, disable_count);
            let options: Vec<MitigationOptions> = slice
                .iter()
                .map(|&opt| MitigationOptions::from(opt))
                .collect();
            Some(options)
        };

        let enable_options = if enable_list.is_null() || enable_count == 0 {
            None
        } else {
            let slice = std::slice::from_raw_parts(enable_list, enable_count);
            let options: Vec<MitigationOptions> = slice
                .iter()
                .map(|&opt| MitigationOptions::from(opt))
                .collect();
            Some(options)
        };

        let eaf_modules_vec = if eaf_modules.is_null() || eaf_modules_count == 0 {
            None
        } else {
            let slice = std::slice::from_raw_parts(eaf_modules, eaf_modules_count);
            let modules: Vec<String> = slice.iter().map(|&ptr| c_string_to_rust(ptr)).collect();
            Some(modules)
        };

        let force_str = if is_force.is_null() {
            None
        } else {
            Some(c_string_to_rust(is_force))
        };

        let is_remove_bool = is_remove != 0;
        let is_reset_bool = is_reset != 0;

        match Program::add_mitigations_for_process(
            &process_name_str,
            disable_options.as_deref(),
            enable_options.as_deref(),
            eaf_modules_vec.as_deref(),
            force_str.as_deref(),
            is_remove_bool,
            is_reset_bool,
        ) {
            app_result if app_result.is_success => CAppResult {
                is_success: 1,
                error_message: ptr::null_mut(),
            },
            app_result => CAppResult {
                is_success: 0,
                error_message: rust_string_to_c(&app_result.error),
            },
        }
    }
}

#[unsafe(no_mangle)]
pub extern "C" fn add_mitigations_to_system(
    disable_list: *const CMitigationOptions,
    disable_count: usize,
    enable_list: *const CMitigationOptions,
    enable_count: usize,
    eaf_modules: *const *const c_char,
    eaf_modules_count: usize,
    is_force: *const c_char,
    is_remove: u8,
    is_reset: u8,
) -> CAppResult {
    unsafe {
        let disable_options = if disable_list.is_null() || disable_count == 0 {
            None
        } else {
            let slice = std::slice::from_raw_parts(disable_list, disable_count);
            let options: Vec<MitigationOptions> = slice
                .iter()
                .map(|&opt| MitigationOptions::from(opt))
                .collect();
            Some(options)
        };

        let enable_options = if enable_list.is_null() || enable_count == 0 {
            None
        } else {
            let slice = std::slice::from_raw_parts(enable_list, enable_count);
            let options: Vec<MitigationOptions> = slice
                .iter()
                .map(|&opt| MitigationOptions::from(opt))
                .collect();
            Some(options)
        };

        let eaf_modules_vec = if eaf_modules.is_null() || eaf_modules_count == 0 {
            None
        } else {
            let slice = std::slice::from_raw_parts(eaf_modules, eaf_modules_count);
            let modules: Vec<String> = slice.iter().map(|&ptr| c_string_to_rust(ptr)).collect();
            Some(modules)
        };

        let force_str = if is_force.is_null() {
            None
        } else {
            Some(c_string_to_rust(is_force))
        };

        let is_remove_bool = is_remove != 0;
        let is_reset_bool = is_reset != 0;

        match Program::add_mitigations_to_system(
            disable_options.as_deref(),
            enable_options.as_deref(),
            eaf_modules_vec.as_deref(),
            force_str.as_deref(),
            is_remove_bool,
            is_reset_bool,
        ) {
            app_result if app_result.is_success => CAppResult {
                is_success: 1,
                error_message: ptr::null_mut(),
            },
            app_result => CAppResult {
                is_success: 0,
                error_message: rust_string_to_c(&app_result.error),
            },
        }
    }
}

#[unsafe(no_mangle)]
pub extern "C" fn import_xml_mitigations(file_path: *const c_char) -> CAppResult {
    if file_path.is_null() {
        return CAppResult {
            is_success: 0,
            error_message: rust_string_to_c("Invalid parameters"),
        };
    }

    unsafe {
        let file_path_str = c_string_to_rust(file_path);

        match Program::import_xml_mitigations(&file_path_str) {
            app_result if app_result.is_success => CAppResult {
                is_success: 1,
                error_message: ptr::null_mut(),
            },
            app_result => CAppResult {
                is_success: 0,
                error_message: rust_string_to_c(&app_result.error),
            },
        }
    }
}

#[unsafe(no_mangle)]
pub extern "C" fn validate_xml_mitigations(
    file_path: *const c_char,
    is_valid: *mut u8,
) -> CAppResult {
    if file_path.is_null() || is_valid.is_null() {
        return CAppResult {
            is_success: 0,
            error_message: rust_string_to_c("Invalid parameters"),
        };
    }

    unsafe {
        let file_path_str = c_string_to_rust(file_path);

        match Program::validate_xml_mitigations(&file_path_str) {
            app_result if app_result.is_success => {
                if let Some(validation_result) = app_result.value {
                    *is_valid = if validation_result { 1 } else { 0 };
                    CAppResult {
                        is_success: 1,
                        error_message: ptr::null_mut(),
                    }
                } else {
                    CAppResult {
                        is_success: 0,
                        error_message: rust_string_to_c("No value returned"),
                    }
                }
            }
            app_result => CAppResult {
                is_success: 0,
                error_message: rust_string_to_c(&app_result.error),
            },
        }
    }
}

#[unsafe(no_mangle)]
pub extern "C" fn export_xml_mitigations(file_path: *const c_char) -> CAppResult {
    if file_path.is_null() {
        return CAppResult {
            is_success: 0,
            error_message: rust_string_to_c("Invalid parameters"),
        };
    }

    unsafe {
        let file_path_str = c_string_to_rust(file_path);

        match crate::GetProcessMitigationCommand::export_mitigation(&file_path_str) {
            Ok(_) => CAppResult {
                is_success: 1,
                error_message: ptr::null_mut(),
            },
            Err(error) => CAppResult {
                is_success: 0,
                error_message: rust_string_to_c(&error),
            },
        }
    }
}

// Memory management functions
#[unsafe(no_mangle)]
pub extern "C" fn free_c_string(ptr: *mut c_char) {
    if !ptr.is_null() {
        unsafe {
            let _ = CString::from_raw(ptr);
        }
    }
}

#[unsafe(no_mangle)]
pub extern "C" fn free_c_string_array(array: CStringArray) {
    if !array.data.is_null() {
        unsafe {
            let slice = std::slice::from_raw_parts_mut(array.data, array.length);
            for ptr in slice.iter() {
                if !ptr.is_null() {
                    let _ = CString::from_raw(*ptr);
                }
            }
            let _ = Vec::from_raw_parts(array.data, array.length, array.length);
        }
    }
}

#[unsafe(no_mangle)]
pub extern "C" fn free_process_mitigations(mitigations: CProcessMitigations) {
    free_c_string(mitigations.process_name);
    free_c_string(mitigations.source);

    if !mitigations.policy_options.data.is_null() {
        unsafe {
            let _ = Vec::from_raw_parts(
                mitigations.policy_options.data,
                mitigations.policy_options.length,
                mitigations.policy_options.length,
            );
        }
    }
}

#[unsafe(no_mangle)]
pub extern "C" fn free_process_mitigations_array(array: CProcessMitigationsArray) {
    if !array.data.is_null() {
        unsafe {
            let slice = Vec::from_raw_parts(array.data, array.length, array.length);
            for mitigations in slice {
                free_process_mitigations(mitigations);
            }
        }
    }
}

#[unsafe(no_mangle)]
pub extern "C" fn free_app_mitigations(mitigations: CAppMitigations) {
    free_c_string(mitigations.process_name);
    free_c_string(mitigations.source);

    if !mitigations.policy_options.data.is_null() {
        unsafe {
            let _ = Vec::from_raw_parts(
                mitigations.policy_options.data,
                mitigations.policy_options.length,
                mitigations.policy_options.length,
            );
        }
    }

    if !mitigations.force_options.data.is_null() {
        unsafe {
            let _ = Vec::from_raw_parts(
                mitigations.force_options.data,
                mitigations.force_options.length,
                mitigations.force_options.length,
            );
        }
    }

    free_c_string_array(mitigations.eaf_modules);
}

#[unsafe(no_mangle)]
pub extern "C" fn free_app_mitigations_array(array: CAppMitigationsArray) {
    if !array.data.is_null() {
        unsafe {
            let slice = Vec::from_raw_parts(array.data, array.length, array.length);
            for mitigations in slice {
                free_app_mitigations(mitigations);
            }
        }
    }
}

#[unsafe(no_mangle)]
pub extern "C" fn free_app_result(result: CAppResult) {
    if !result.error_message.is_null() {
        free_c_string(result.error_message);
    }
}
